package cn.juque.redoctopus.convert;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.juque.luceneplus.dto.SearchAfterRequestDTO;
import cn.juque.redoctopus.api.constants.LogIndexEnum;
import cn.juque.redoctopus.bo.LogSearchBO;
import cn.juque.redoctopus.bo.field.FieldDocBO;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BooleanQuery.Builder;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.SortField.Type;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.WildcardQuery;

/**
 * @author nuoka
 * @version 1.0.0
 * <li></li>
 * @date 2021/11/13 19:22
 **/
public class SearchAfterRequestDTOConverter {

    /**
     * 转换成plus的查询条件
     * @param logSearchBO 入参
     * @return SearchAfterRequestDTO
     */
    public static SearchAfterRequestDTO toSearchAfterRequestDTO(LogSearchBO logSearchBO) {
        BooleanQuery.Builder builder = new Builder();
        if(CharSequenceUtil.isNotEmpty(logSearchBO.getKeyword())) {

            BooleanQuery.Builder childBuilder = new Builder();
            WildcardQuery serviceNoQuery = new WildcardQuery(new Term(LogIndexEnum.SERVICE_NO.getCode(), "*" + logSearchBO.getKeyword() + "*"));
            childBuilder.add(serviceNoQuery, Occur.SHOULD);
            WildcardQuery serviceNameQuery = new WildcardQuery(new Term(LogIndexEnum.SERVICE_NAME.getCode(),"*" + logSearchBO.getKeyword() + "*"));
            childBuilder.add(serviceNameQuery, Occur.SHOULD);
            WildcardQuery messageQuery = new WildcardQuery(new Term(LogIndexEnum.MESSAGE.getCode(), "*" + logSearchBO.getKeyword() + "*"));
            childBuilder.add(messageQuery, Occur.SHOULD);
            WildcardQuery throwableQuery = new WildcardQuery(new Term(LogIndexEnum.THROWABLE.getCode(), "*" + logSearchBO.getKeyword() + "*"));
            childBuilder.add(throwableQuery, Occur.SHOULD);
            builder.add(childBuilder.build(), Occur.MUST);
        }
        if(CharSequenceUtil.isNotEmpty(logSearchBO.getServiceNo())) {
            PrefixQuery prefixQuery = new PrefixQuery(new Term(LogIndexEnum.SERVICE_NO.getCode(), logSearchBO.getServiceNo()));
            builder.add(prefixQuery, Occur.MUST);
        }
        if(CharSequenceUtil.isNotEmpty(logSearchBO.getServiceName())) {
            PrefixQuery prefixQuery = new PrefixQuery(new Term(LogIndexEnum.SERVICE_NAME.getCode(), logSearchBO.getServiceName()));
            builder.add(prefixQuery, Occur.MUST);
        }
        if(CharSequenceUtil.isNotEmpty(logSearchBO.getLevel())) {
            TermQuery termQuery = new TermQuery(new Term(LogIndexEnum.LEVEL.getCode(), logSearchBO.getLevel()));
            builder.add(termQuery, Occur.MUST);
        }
        if(CharSequenceUtil.isNotEmpty(logSearchBO.getIp())) {
            FuzzyQuery ipQuery = new FuzzyQuery(new Term(LogIndexEnum.IP.getCode(), logSearchBO.getIp()));
            builder.add(ipQuery, Occur.MUST);
        }
        if(ObjectUtil.isAllNotEmpty(logSearchBO.getStartTime(), logSearchBO.getEndTime())) {
            Query query = LongPoint.newRangeQuery(LogIndexEnum.LOG_TIME.getCode(), logSearchBO.getStartTime().getTime(), logSearchBO.getEndTime().getTime());
            builder.add(query, Occur.MUST);
        }
        SearchAfterRequestDTO searchAfterRequestDTO = new SearchAfterRequestDTO();
        searchAfterRequestDTO.setIndexName(LogIndexEnum.INDEX_NAME.getCode());
        searchAfterRequestDTO.setBuilder(builder);
        if(CharSequenceUtil.isNotEmpty(logSearchBO.getLastScoreByte())) {
            FieldDocBO fieldDocBO = ObjectUtil.deserialize(Base64.decode(logSearchBO.getLastScoreByte()));
            searchAfterRequestDTO.setLastScoreDoc(FieldDocConverter.toFieldDoc(fieldDocBO));
        }
        Integer size = null == logSearchBO.getPageSize() ? 50 : logSearchBO.getPageSize();
        searchAfterRequestDTO.setPageSize(size);
        // 日志时间倒序
        SortField sortField = new SortField(LogIndexEnum.LOG_TIME.getCode(), Type.LONG, true);
        Sort sort = new Sort(sortField);
        searchAfterRequestDTO.setSort(sort);

        return searchAfterRequestDTO;
    }
}
